package jcu.salt.client;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.rbnb.sapi.ChannelMap;

import jcu.salt.Logger;
import jcu.salt.io.Receiver;
import jcu.salt.io.Transmittable;

/**
 * 
 * Maintains the connections to the data turbine by use of several
 * threads (one for each source channel available) as well as the connection
 * to the SRB to write all received data from any of the listening threads
 * to the SRB-connection established during object creation.
 * 
 * @author SAL-T team
 *
 */
public class SaltSRBClient implements SRBClient {

	private List<TurbineReceiverThread> receivers;

	private SRBConnection srb = null;

	/**
	 * establishes the SRB connection and start a receiver thread for each
	 * channel available
	 * 
	 * @param host
	 * @param sink
	 * @param cmap
	 */
	public SaltSRBClient(String host, String sink, ChannelMap cmap) {

		Logger.log("Create an instance for the SRB connection");
		srb = new SRBConnection();
		receivers = new ArrayList<TurbineReceiverThread>();

		Logger.log("Creating threads for " + cmap.NumberOfChannels()
				+ " channels");
		for (String channel : cmap.GetChannelList()) {
			Logger.log("creating receiver thread for channel " + channel);
			receivers
					.add(new TurbineReceiverThread(new Receiver(channel), this));
		}

	}
	
	
	/** 
	 * implements the handler/callback routine to write data to the established 
	 * SRB connection 
	 */
	@Override
	public void writeData(Transmittable received) {
		try {
			srb.writeData(received);
		} catch (NullPointerException e) {
			System.out.println("\nProcess failed.\n");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("\nProcess failed.\n");
			e.printStackTrace();
		} catch (DataTypeNotRecognizedException e) {
			System.out.println("\nProcess failed.\n");
			e.printStackTrace();
		}
	}

	/**
	 * starts the receiver threads (for each channel)
	 */
	public void start() {
		for (TurbineReceiverThread thread : receivers) {
			Logger.log("creating receiver thread for channel "
					+ thread.getChannel());
			thread.start();
		}
		Logger.log("start receiver thread");
	}

	/**
	 * stops the receiver threads
	 */
	public void stop() {
		Logger.log("stop receiver threads");
		for (TurbineReceiverThread thread : receivers) {
			Logger.log("deactivationg receiver thread for channel "
					+ thread.getChannel());
			thread.setActive(false);
		}
		for (TurbineReceiverThread thread : receivers) {
			try {
				Logger.log("waiting for receiver thread for channel "
						+ thread.getChannel());
				thread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}
}
